<?php


namespace common\helpers;


use common\models\System;
use EasyWeChat\Factory;

/**
 * 微信接口
 * Class WeChatApi
 * @package common\helpers
 */
class WeChatApi
{
    private $config = [];
    public function __construct($config)
    {
        $this->config = $config;
    }

    /**
     * 小程序支付
     * @param $order_sn 订单号
     * @param $amount 支付金额
     * @param $notify_url 回调地址
     * @param $openid 用户openid
     * @param $goodName 商品名称
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function appletsPay($order_sn,$amount,$notify_url,$openid,$goodName)
    {
        $notify_url = commonApi::getDomain($notify_url);
        try {
            if (empty($this->config['app_id'])||empty($this->config['mch_id'])||empty($this->config['key'])){
                throw new \Exception('请配置微信支付参数！');
            }
            $app = Factory::payment($this->config);
            $result = $app->order->unify([
                'body'=>$goodName,
                'out_trade_no'=>$order_sn,
                'total_fee'=>$amount*100,
                'notify_url'=>$notify_url,
                'trade_type'=>'JSAPI',
                'openid'=>$openid,
            ]);
            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS' && isset($result['prepay_id'])){
                $config = $app->jssdk->bridgeConfig($result['prepay_id'], false); // 返回数组
                $config['is_pay'] = 1;
                return commonApi::message('等待支付',true,$config);
            }
            $ms = empty($result['err_code_des'])?$result['return_msg']:$result['err_code_des'];
            throw new \Exception($ms);
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
    }

    /**
     * 小程序授权
     * @param $code code
     * @param $rawData 前端解析的用户信息 json字符串
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function appletsLogin($code,$rawData)
    {
        if (!$code){
            return commonApi::message('请授权！',false);
        }
        $wechat = json_decode($rawData, true);
        if (!$wechat) {
            return commonApi::message('数据错误！',false);
        }
        $this->config['response_type'] = 'array';
        try {
            $app = Factory::miniProgram($this->config);
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
        $data = $app->auth->session($code);
        //判断code是否过期
        if (isset($data['errcode'])) {
            return commonApi::message('code已过期或不正确',false);
        }
        $weappOpenid = $data['openid'];
        return commonApi::message('ok',true,['openid'=>$weappOpenid,'data'=>$wechat,'authData'=>$data]);
    }

    /**
     * 获取小程序码
     * @param $path 路径
     * @param $scene 标识
     * @param array $option 额外参数
     * @return array
     */
    public function appletsQr($path,$scene,$option=[])
    {
        $option['page'] = $path;
        try {
            if (empty($this->config['app_id'])||empty($this->config['secret'])){
                throw new \Exception('请配置微信参数！');
            }
            $this->config['response_type'] = 'array';
            $app = Factory::miniProgram($this->config);
            $response = $app->app_code->getUnlimit($scene,$option);
            if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $contents = $response->getBody()->getContents();
                $contents = base64_encode($contents);
                return commonApi::message('ok',true,['img'=>'data:image/jpeg;base64,'.$contents]);
            }
            throw new \Exception('获取失败');
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
    }

    /**
     * 支付回调
     * @param callable $fun
     * @return array|void
     */
    public function payNotify($class,$method)
    {
        try {
            if (empty($this->config['app_id'])||empty($this->config['mch_id'])||empty($this->config['key'])){
                throw new \Exception('请配置微信支付参数！');
            }
            $app = Factory::payment($this->config);
            $response = $app->handlePaidNotify(function ($message, $fail)use ($class,$method){
                $result = true;
                if ($class&&$method){
                    $result = (new $class)->{$method}($message);
                }
                if (!$result){
                    return $fail('通信失败，请稍后再通知我');
                }
                return true; // 返回处理完成
            });
            $response->send();
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
    }

    /**
     * 企业付款到零钱
     * @param $orderid
     * @param $openid
     * @param $amount
     * @param $desc
     * @return array
     */
    public function transferToBalance($orderid,$openid,$amount,$desc='付款')
    {
        try {
            if (empty($this->config['app_id'])||empty($this->config['mch_id'])||empty($this->config['key'])){
                throw new \Exception('请配置微信支付参数！');
            }
            $app = Factory::payment($this->config);
            $result = $app->transfer->toBalance([
                'partner_trade_no'=>$orderid,
                'amount'=>$amount*100,
                'openid'=>$openid,
                'desc'=>$desc,
            ]);
            if (!empty($result['result_code']) && $result['return_code'] === 'SUCCESS'&& $result['result_code'] === 'SUCCESS'){
                return commonApi::message('付款成功',true,$result);
            }
            $ms = empty($result['err_code_des'])?$result['return_msg']:$result['err_code_des'];
            throw new \Exception($ms);
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
    }

    /**
     * 微信退款
     * @param $orderSn 下单订单号
     * @param $orderAmount 下单支付金额
     * @param $refundNumber 退款订单号
     * @param $refundFee 退款金额
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function refund($orderSn,$orderAmount,$refundNumber,$refundFee)
    {
        try {
            if (empty($this->config['app_id'])||empty($this->config['mch_id'])||empty($this->config['key'])||empty($this->config['cert_path'])||empty($this->config['key_path'])){
                throw new \Exception('请配置微信支付参数！');
            }
            $payment = Factory::payment($this->config);
            $result = $payment->refund->byOutTradeNumber($orderSn, $refundNumber, $orderAmount*100, $refundFee*100, [
                'refund_desc' => $orderSn.'-退款',
            ]);
            if ($result['return_code'] == 'SUCCESS' && $result['return_msg'] == 'OK'){
                if (empty($result['err_code_des'])) {
                    return commonApi::message('退款成功',true,$result);
                }
            }
            $ms = empty($result['err_code_des'])?$result['return_msg']:$result['err_code_des'];
            throw new \Exception($ms);
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }

    }

    /**
     * 授权手机号
     * @param $code
     * @return array
     */
    public function phoneNumber($code)
    {
        try {
            if (!$code){
                throw new \Exception('请授权！');
            }
            if (empty($this->config['app_id'])||empty($this->config['secret'])){
                throw new \Exception('请配置微信参数！');
            }
            $payment = Factory::payment($this->config);
            $result = $payment->phone_number->getUserPhoneNumber($code);
            if ($result['errcode']==0&&$result['errmsg']=='ok'&&!empty($result['phone_info']['phoneNumber'])){
                return commonApi::message('获取成功',true,['mobile'=>$result['phone_info']['phoneNumber']]);
            }
            $ms = empty($result['errmsg'])?$result['errmsg']:'获取手机号失败';
            throw new \Exception($ms);
        }catch (\Throwable $e){
            return commonApi::message($e->getMessage(),false);
        }catch (\Exception $e){
            return commonApi::message($e->getMessage(),false);
        }
    }
}